package br.com.ema.maze.components;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import br.com.ema.maze.agents.MazeCharacter;
import br.com.ema.maze.agents.WallPassageAllowerAgent;
import br.com.ema.maze.listeners.MazeComponentContentChangeListener;
import br.com.ema.maze.listeners.MazeContentChangeListener;

/**
 * @author Emanuel Cruz Rodrigues -> emanuelcruzrodrigues@gmail.com
 *
 */
public class Maze extends MazeComponent{
	
	private Map<Coordinates, MazeSpace> spaces;
	private List<MazeContentChangeListener> mazeContentChangeListeners;
	private List<WallPassageAllowerAgent> wallPassageAllowerAgents;
	private MazeSpace exit;
	private Map<String, MazeCharacter> characters;
	
	public Maze() {
		spaces = new HashMap<Coordinates, MazeSpace>();
		mazeContentChangeListeners = new ArrayList<MazeContentChangeListener>();
		wallPassageAllowerAgents = new ArrayList<WallPassageAllowerAgent>();
		characters = new HashMap<String, MazeCharacter>();
	}
	
	public void addSpace(final MazeSpace space) {
		space.setMaze(this);
		spaces.put(space.getCoordinates(), space);
		space.addContentListener(new MazeComponentContentChangeListener() {
			@Override
			public void contentChanged(MazeComponent mazeComponent) {
				callMazeContentChangeListeners(space);
			}
		});
	}

	public MazeSpace getSpace(int x, int y) {
		return getSpace(new Coordinates(x, y));
	}
	
	public MazeSpace getSpace(Coordinates coordinates) {
		return spaces.get(coordinates);
	}
	
	public void addMazeContentChangeListener(MazeContentChangeListener mazeContentChangeListener){
		mazeContentChangeListeners.add(mazeContentChangeListener);
	}
	
	public void callMazeContentChangeListeners(MazeComponent componentChanged){
		for (MazeContentChangeListener mazeListener : mazeContentChangeListeners) {
			mazeListener.mazeContentChanged(componentChanged);
		}
	}

	public int getWidth() {
		int width = 0;
		for (Coordinates coordinates : spaces.keySet()) {
			if (coordinates.getX() > width){
				width = coordinates.getX();
			}
		}
		return width + 1;
	}

	public int getHeight() {
		int height = 0;
		for (Coordinates coordinates : spaces.keySet()) {
			if (coordinates.getY() > height){
				height = coordinates.getY();
			}
		}
		return height + 1;
	}

	public void addWallPassageAllower(WallPassageAllowerAgent allower) {
		wallPassageAllowerAgents.add(allower);
	}
	
	public Collection<MazeSpace> getSpaces() {
		return spaces.values();
	}
	
	public void setExit(int x, int y) {
		this.setExit(new Coordinates(x, y));
	}


	public void setExit(Coordinates coordinates) {
		if (exit != null){
			exit.setDecoration(null);
		}
		
		MazeSpace space = getSpace(coordinates);
		if (space != null){
			space.setDecoration(new MazeExit());
		}
		
		exit = space;
	}
	
	public Collection<MazeCharacter> getCharacters() {
		return characters.values();
	}
	
	public void addCharacter(String characterId, MazeCharacter character){
		characters.put(characterId, character);
	}
	
	public MazeCharacter getCharacter(String characterId){
		return characters.get(characterId);
	}
	
	
	public List<WallPassageAllowerAgent> getWallPassageAllowerAgents() {
		return wallPassageAllowerAgents;
	}
	
	public MazeSpace getExit() {
		return exit;
	}

}
